#ifndef __M_LOOPER_HPP__
#define __M_LOOPER_HPP__

//实现异步工作器
#include <iostream>
#include <string>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <functional>
#include <atomic>
#include "level.hpp"
#include "buffer.hpp"
#include "logger.hpp"

namespace mylog
{
    using Functor = std::function<void(Buffer&)>;
    enum class AsyncType
    {
        ASYNC_SAFE, //异步安全，表示缓冲区满了则阻塞，避免资源耗尽的风险
        ASYNC_UNSAFE //异步不安全，表示缓冲区满了则自动扩容，有资源耗尽的风险
    };
    class AsyncLooper  
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        AsyncLooper(const Functor& callBack, AsyncType looper_Type = AsyncType::ASYNC_SAFE)
            :_looper_Type(looper_Type),_stop(false), _callBack(callBack), _thread(std::thread(&AsyncLooper::threadEntry,this))
        {}
        ~AsyncLooper()
        {
            stop();
        }
        void stop()
        {
            _stop = true;
            _cond_con.notify_all(); //唤醒消费线程
            if(_thread.joinable())
                _thread.join();
        }
        void push(const char* data, size_t len)
        {
            //1、无限扩容-非安全   2、固定大小-生产缓冲区数据满了就阻塞
            std::unique_lock<std::mutex> lock(_mutex);
            if(_looper_Type == AsyncType::ASYNC_SAFE)
                _cond_pro.wait(lock,[&]{return _pro_buf.writeAbleSize() >= len;});
            _pro_buf.push(data, len);
            _cond_con.notify_one(); //唤醒消费线程
        }
    private:
        //工作线程入口
        void threadEntry()
        {
            while(1)
            {
                //1、判断生产缓冲区有没有数据，有则交换，无则阻塞
                //互斥锁设置生命周期（当缓冲区交换完毕后就解锁，处理过程不需要保护）
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    //退出标志被设置，且生产缓冲区已经没有数据，这时候再退出，否则又可能会造成缓冲区中有数据，但是没有被完全处理
                    if(_stop && _pro_buf.empty())
                        break;
                    _cond_con.wait(lock,[&]{return _pro_buf.readAbleSize() > 0 || _stop;});
                    _con_buf.swap(_pro_buf);
                    //2、唤醒生产者
                    if(_looper_Type == AsyncType::ASYNC_SAFE)
                        _cond_pro.notify_all();
                }
                //3、被唤醒后，对消费缓冲区进行数据处理
                _callBack(_con_buf);
                //4、初始化消费缓冲区
                _con_buf.reset();
            }
        } 
    private:
        Functor _callBack; //回调函数
    private:
        AsyncType _looper_Type; //异步类型
        std::atomic <bool> _stop; //工作器停止标志
        Buffer _pro_buf; //生产缓冲区
        Buffer _con_buf; //消费缓冲区
        std::mutex _mutex; //互斥锁
        std::condition_variable _cond_pro; //条件变量
        std::condition_variable _cond_con; //条件变量
        std::thread _thread; //工作线程
    };
}

#endif